package com.hundsun.epay.autosimu.api.dom.java;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.hundsun.epay.autosimu.api.dom.OutputUtility;

/**
 * 内部类
 * @author Clown
 *
 */
public class InnerClass extends JavaElement {
	private FullyQualifiedJavaType type;   //自身类型
	private boolean isAbstract;   //是否抽象
	private List<Field> fields;   //属性
	private List<InitializationBlock> initBlocks;   //初始化块
	private List<Method> methods;    //方法
	private List<InnerClass> innerClasses;    //内部类
	private List<InnerEnumeration> innerEnums;    //内部枚举
	private List<TypeParameter> typeParameters;    //类型参数
	private Set<FullyQualifiedJavaType> superInterfaceTypes;    //实现接口
	private FullyQualifiedJavaType superClass;    //父类
	
	public InnerClass(FullyQualifiedJavaType type) {
		super();
		this.type = type;
		this.isAbstract = false;
		this.fields = new ArrayList<Field>();
		this.initBlocks = new ArrayList<InitializationBlock>();
		this.innerClasses = new ArrayList<InnerClass>();
		this.innerEnums = new ArrayList<InnerEnumeration>();
		this.methods = new ArrayList<Method>();
		this.superInterfaceTypes = new HashSet<FullyQualifiedJavaType>();
		this.typeParameters = new ArrayList<TypeParameter>();
	}
	
	public InnerClass(String type){
		this(new FullyQualifiedJavaType(type));
	}

	public FullyQualifiedJavaType getType() {
		return type;
	}

	public void setType(FullyQualifiedJavaType type) {
		this.type = type;
	}

	public boolean isAbstract() {
		return isAbstract;
	}

	public void setAbstract(boolean isAbstract) {
		this.isAbstract = isAbstract;
	}

	public FullyQualifiedJavaType getSuperClass() {
		return superClass;
	}

	public void setSuperClass(FullyQualifiedJavaType superClass) {
		this.superClass = superClass;
	}

	public List<Field> getFields() {
		return fields;
	}

	public List<InitializationBlock> getInitBlocks() {
		return initBlocks;
	}

	public List<Method> getMethods() {
		return methods;
	}

	public List<InnerClass> getInnerClasses() {
		return innerClasses;
	}

	public List<InnerEnumeration> getInnerEnums() {
		return innerEnums;
	}

	public List<TypeParameter> getTypeParameters() {
		return typeParameters;
	}

	public Set<FullyQualifiedJavaType> getSuperInterfaceTypes() {
		return superInterfaceTypes;
	}
	
	public void addField(Field field){
		this.fields.add(field);
	}
	
	public void addInitializationBlock(InitializationBlock initBlock){
		this.initBlocks.add(initBlock);
	}
	
	public void addMethod(Method method){
		this.methods.add(method);
	}
	
	public void addInnerClass(InnerClass innerClass){
		this.innerClasses.add(innerClass);
	}
	
	public void addInnerEnumeration(InnerEnumeration innerEnum){
		this.innerEnums.add(innerEnum);
	}
	
	public void addTypeParameter(TypeParameter type){
		this.typeParameters.add(type);
	}
	
	public void addSuperInterfaceType(FullyQualifiedJavaType interfaceType){
		this.superInterfaceTypes.add(interfaceType);
	}
	
	public String getFormattedContent(int indentLevel, CompilationUnit unit){
		StringBuilder sb = new StringBuilder();
		
		//注释注解
		addFormattedJavaDocLines(sb, indentLevel);
		addFormattedAnnotation(sb, indentLevel);
		
		//修饰符
		OutputUtility.javaIndent(sb, indentLevel);
		sb.append(getVisibility().getDesc());
		
		if(isStatic()){
			sb.append("static ");
		}
		
		if(isAbstract){
			sb.append("abstract ");
		}
		
		if(isFinal()){
			sb.append("final ");
		}
		
		//类声明
		sb.append("class ");
		sb.append(type.getShortName());
		
		if(!typeParameters.isEmpty()){
			sb.append("<");
			boolean first = true;
			for (TypeParameter typeParameter : typeParameters) {
				if(first){
					first = false;
				}else{
					sb.append(", ");
				}
				sb.append(typeParameter.getFormattedContent(unit));
			}
			sb.append(">");
		}
		
		//继承与实现
		if(superClass != null){
			sb.append(" extends ");
			sb.append(JavaDomUtils.calculateTypeName(unit, superClass));
		}
		
		if(!superInterfaceTypes.isEmpty()){
			sb.append(" implements ");
			boolean first = true;
			for (FullyQualifiedJavaType interfaceType : superInterfaceTypes) {
				if(first){
					first = false;
				}else{
					sb.append(", ");
				}
				sb.append(JavaDomUtils.calculateTypeName(unit, interfaceType));
			}
		}
		
		sb.append(" {");
		indentLevel ++;
		
		//属性
		Iterator<Field> fieldListIterator = fields.iterator();
		while(fieldListIterator.hasNext()) {
			OutputUtility.newLine(sb);
			sb.append(fieldListIterator.next().getFormattedContent(indentLevel, unit));
			if(fieldListIterator.hasNext()){
				OutputUtility.newLine(sb);
			}
		}
		
		if(!initBlocks.isEmpty()){
			OutputUtility.newLine(sb);
		}
		
		//初始化块
		Iterator<InitializationBlock> ibIterator = initBlocks.iterator();
		while(ibIterator.hasNext()){
			OutputUtility.newLine(sb);
			sb.append(ibIterator.next().getFormattedContent(indentLevel));
			if(ibIterator.hasNext()){
				OutputUtility.newLine(sb);
			}
		}
		
		if(!methods.isEmpty()){
			OutputUtility.newLine(sb);
		}
		
		//方法
		Iterator<Method> methodIterator = methods.iterator();
		while(methodIterator.hasNext()){
			OutputUtility.newLine(sb);
			sb.append(methodIterator.next().getFormattedContent(unit, indentLevel, false));
			if(methodIterator.hasNext()){
				OutputUtility.newLine(sb);
			}
		}
		
		if(!innerClasses.isEmpty()){
			OutputUtility.newLine(sb);
		}
		
		//内部类
		Iterator<InnerClass> innerClassIterator = innerClasses.iterator();
		while(innerClassIterator.hasNext()){
			OutputUtility.newLine(sb);
			sb.append(innerClassIterator.next().getFormattedContent(indentLevel, unit));
			if(innerClassIterator.hasNext()){
				OutputUtility.newLine(sb);
			}
		}
		
		if(!innerEnums.isEmpty()){
			OutputUtility.newLine(sb);
		}
		
		//内部枚举
		Iterator<InnerEnumeration> innerEnumIterator = innerEnums.iterator();
		while(innerEnumIterator.hasNext()){
			OutputUtility.newLine(sb);
			sb.append(innerEnumIterator.next().getFormattedContent(indentLevel, unit));
			if(innerEnumIterator.hasNext()){
				OutputUtility.newLine(sb);
			}
		}
		
		indentLevel --;
		OutputUtility.newLine(sb);
		OutputUtility.javaIndent(sb, indentLevel);
		sb.append("}");
		
		return sb.toString();
	}
}
